/**
 * @author randomize
 * @param {HTMLElement} elem 需要绑定监听的DOM元素
 * @param {String} type 要绑定的事件类型
 * @param {String} selector 需要进行筛选的nodeName
 * @param {Function} fn 自定义监听事件的回调函数,不要传入箭头函数！
 */

function bindEvent (elem, type, selector, fn) {
  // 如果只传入三个参数，那么第三个参数是fn而不是selector
  // 这一步必须用'=='，因为undefined == null 返回true
  if (fn == null) {
    fn = selector
    selector = null
  }

  elem.addEventListener(type, event => {
    // 获取触发事件的元素
    const target = event.target
    // 如果传入了selector，说明需要用到事件代理
    if (selector) {
      // 代理绑定
      // target.matches,判断dom元素是否符合css选择器
      if (target.matches(selector)) {
        fn.call(target, event)
      }
    } else {
      // 普通绑定
      fn.call(target, event)
    }
  })
}

// 普通绑定
const btn = document.querySelector('#btn1')
// 此处不要写成箭头函数，因为箭头函数调用call不会改变this指向！
bindEvent(btn, 'click', function (e) {
  e.preventDefault()
  alert(this.innerHTML)
})

// 代理绑定
const div = document.querySelector('#div3')
bindEvent(div, 'click', 'A', function (e) {
  event.preventDefault()
  alert(this.innerHTML)
})

// html测试
{/* <div id="div3">
    <a href="#">a1</a>
    <a href="#">a2</a>
    <a href="#">a3</a>
    <a href="#">a4</a>
  </div>
  <button id="btn1">点我触发</button> */}
